﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Core.Sdk.WeiXin.Tool
{


    public class SHAFile
    {
        /// 计算文件的 SHA256 值
        /// 
        /// 要计算 SHA256 值的文件名和路径
        /// SHA256值16进制字符串
        public static string SHA256File(string fileName)
        {
            return HashFile(fileName, "sha256");
        }

        /// <summary>
        /// 计算文件的哈希值
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <param name="algName">算法:sha1,md5</param>
        /// <returns></returns>
        private static string HashFile(string fileName, string algName)
        {
            if (!File.Exists(fileName))
                return string.Empty;

            byte[] hashBytes = { };
            using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                hashBytes = HashData(fs, algName);
            }
            return ByteArrayToHexString(hashBytes);
        }



        /// <summary>
        /// 字节数组转换为16进制表示的字符串
        /// </summary>
        /// <param name="buf"></param>
        /// <returns></returns>
        private static string ByteArrayToHexString(byte[] buf)
        {
            if (buf == null || buf.Length == 0)
                return string.Empty;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < buf.Length; i++)
            {
                sb.Append(buf[i].ToString("X2"));
            }
            return sb.ToString();
        }


        /// <summary>
        /// 计算哈希值
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="algName"> 算法:sha1,md5</param>
        /// <returns></returns>
        private static byte[] HashData(Stream stream, string algName)
        {
            HashAlgorithm algorithm;
            if (string.IsNullOrEmpty(algName))
            {
                throw new ArgumentNullException("algName 不能为 null");
            }
            if (string.Compare(algName, "sha256", true) == 0)
            {
                algorithm = SHA256.Create();
            }
            else if (string.Compare(algName, "md5", true) == 0)
            {
                algorithm = MD5.Create();
            }
            else
                throw new Exception("algName 只能使用 sha256 或 md5");

            return algorithm.ComputeHash(stream);
        }
    }
}
